package org.workplicity.marist.grounds.util;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

/**
 *
 * @author Elliott Picker & Stephen Horn
 */
public class Report {

    public static int numWarnings = 0;
    public static int numPurged = 0;
    public static int numRepaired = 0;
    public static boolean notBeenPurged = true;

    // This enumerated type is used to allow the report to know what kind of alert
    // is being added to the report and adds the text to the appropriate place
    // on the report
    public enum alertType {

        servicesWithoutUsers, usersWithoutServices, futuresWithInvalidTemplates, enabledAndExpiredFutures,
        usersWithIdenticalLogNames, duplicateIds, requestsWithInvalidServiceReferences, invalidOrMissingLogName,
        invalidPassword, badTime, badWorkSlateId, badServiceId, duplicateWorkSlate, duplicateService,
        requestsNotOnWorkSlate, oldClosedRequests, futuresWithInvalidTemplate, oldFutureEvents, invalidCreateDate,
        invalidUpdateUser, invalidUpdateDate
    }
    static String[] warnings = new String[9];
    static String[] purged = new String[4];
    static ArrayList<String> repaired = new ArrayList<String>();
    static String warns;

    /**
     * This method sets the number of warnings and number of purged entries to zero
     * as well as setting the report text for each type of alert to a null string
     */
    public static void init() {
        numWarnings = 0;
        resetWarnings();
        numPurged = 0;
        //Set each index in the purge array to empty string
        for (int j = 0; j < 4; j++) {
            purged[j] = "";
        }
        numRepaired = 0;

    }

    public static void resetWarnings() {
        numWarnings = 0;
        for (int i = 0; i < 9; i++) {
            warnings[i] = "";
        }
    }

    public static int getNumWarnings() {
        return numWarnings;
    }

    public static void resetNumRepaired() {
        numRepaired = 0;
    }

    public static int getNumRepaired() {
        return numRepaired;
    }

    public static void resetNumPurged() {
        numPurged = 0;
    }

    public static int getNumPurged() {
        return numPurged;
    }

    /**
     * This method is called by the individual methods of the repair, purge, and warn
     * tabs when a change or warning occurs, and the information regarding the change
     * or warning is added to the report text
     * @param type the type of alert which is being added to the report
     * @param data the informational text about the alert
     */
    public static void add(alertType type, String data) {

        switch (type) {
            case invalidCreateDate:
                repaired.add(data);
                numRepaired++;
                break;
            case invalidUpdateUser:
                repaired.add(data);
                numRepaired++;
                break;
            case invalidUpdateDate:
                repaired.add(data);
                numRepaired++;
                break;
            case badWorkSlateId:
                repaired.add(data);
                numRepaired++;
                break;
            case badServiceId:
                repaired.add(data);
                numRepaired++;
                break;
            case duplicateWorkSlate:
                repaired.add(data);
                numRepaired++;
                break;
            case duplicateService:
                repaired.add(data);
                numRepaired++;
                break;
            case servicesWithoutUsers:
                warnings[0] += (data + "\n");
                numWarnings++;
                break;
            case usersWithoutServices:
                warnings[1] += (data + "\n");
                numWarnings++;
                break;
            case futuresWithInvalidTemplates:
                warnings[2] += (data + "\n");
                numWarnings++;
                break;
            case enabledAndExpiredFutures:
                warnings[3] += (data + "\n");
                numWarnings++;
                break;
            case usersWithIdenticalLogNames:
                warnings[4] += (data + "\n");
                numWarnings++;
                break;
            case duplicateIds:
                warnings[5] += (data);
                numWarnings++;
                break;
            case requestsWithInvalidServiceReferences:
                warnings[6] += (data + "\n");
                numWarnings++;
                break;
            case invalidOrMissingLogName:
                warnings[7] += (data + "\n");
                numWarnings++;
                break;
            case invalidPassword:
                warnings[8] += (data + "\n");
                numWarnings++;
                break;
            case requestsNotOnWorkSlate:
                purged[0] += (data);
                numPurged++;
                notBeenPurged = false;
                break;
            case oldClosedRequests:
                purged[1] += (data);
                numPurged++;
                notBeenPurged = false;
                break;
            case futuresWithInvalidTemplate:
                purged[2] += (data);
                notBeenPurged = false;
                numPurged++;
                break;
            case oldFutureEvents:
                purged[3] += (data);
                notBeenPurged = false;
                numPurged++;
                break;
            default:
                break;
        }
    }

    public static void add(alertType type) {
        switch (type) {
            case requestsNotOnWorkSlate:
                purged[0] += "NOTHING FOUND \n";

                break;
            case oldClosedRequests:
                purged[1] += "NOTHING FOUND \n";

                break;
            case futuresWithInvalidTemplate:
                purged[2] += "NOTHING FOUND \n";

                break;
            case oldFutureEvents:
                purged[3] += "NOTHING FOUND \n";

                break;
            default:
                break;
        }
    }

    /**
     * This method generates the text which will be displayed in the report
     * @return allErrors the string of text contained by the report
     */
    public static String output() {

        DateFormat dateFormat = new SimpleDateFormat("MM/dd/yyyy HH:mm:ss");
        Date date = new Date();
        String currentDateAndTime = dateFormat.format(date);
        String format = "****************************************************\nGauntlet Report - generated on " + currentDateAndTime
                + "\n****************************************************\n\n";
        String allErrors = "";
        allErrors += format + "\n--------\nRepairs\n--------\n\n";
        if (repaired.size() > 0) {
            for (int i = 0; i < repaired.size(); i++) {
                allErrors += repaired.get(i) + "\n";
            }
        } else {
            allErrors += "No repairs were made\n\n";
        }

        allErrors += "\n--------\nWarnings\n--------\n\n";
        if (numWarnings == 0) {
            allErrors += "System checked with no Warnings\n\n";
        } else {
            allErrors += "Found " + numWarnings + " errors: \n";
            if (!warnings[0].isEmpty()) {
                allErrors += "The following Service(s) do not have Users: \n" + warnings[0] + "\n \n";
            }
            if (!warnings[1].isEmpty()) {
                allErrors += "The following User(s) do not have Services: \n" + warnings[1] + "\n \n";
            }
            if (!warnings[2].isEmpty()) {
                allErrors += "The following Future(s) have invalid Templates: \n" + warnings[2] + "\n \n";
            }
            if (!warnings[3].isEmpty()) {
                allErrors += "The following enabled future(s) have already expired: \n" + warnings[3] + "\n \n";
            }
            if (!warnings[4].isEmpty()) {
                allErrors += "The following logname(s) appear more than once: \n" + warnings[4] + "\n \n";
            }
            if (!warnings[5].isEmpty()) {
                allErrors += "The following entries have the same id: \n" + warnings[5] + "\n \n";
            }
            if (!warnings[6].isEmpty()) {
                allErrors += "The following request(s) have invalid or missing service refrences: \n" + warnings[6] + "\n \n";
            }
            if (!warnings[7].isEmpty()) {
                allErrors += "The following user(s) have invalid or missing username(s): \n" + warnings[7] + "\n \n";
            }
            if (!warnings[8].isEmpty()) {
                allErrors += "The following user(s) have invalid or insecure password(s): \n" + warnings[8] + "\n \n";
            }

        }

        /******************************************
         * PURGED SECTION
         *****************************************/
        //Start of Purge section of Report
        allErrors += "\n--------\nPurged\n--------\n\n";
        //Check to see if nothing was purged
        if ((numPurged == 0) && notBeenPurged) {
            allErrors += "Nothing was purged \n";
        } else {
            //For each purge,check to see if empty. If not, add to allErrors string the appropriate data
            if (!purged[0].isEmpty()) {
                allErrors += "The following request(s) were not on a Work Slate: \n" + purged[0] + "\n \n";
            }
            if (!purged[1].isEmpty()) {
                allErrors += "The following request(s) were old and closed: \n" + purged[1] + "\n \n";
            }
            if (!purged[2].isEmpty()) {
                allErrors += "The following Future(s) had an Invalid Template: \n" + purged[2] + "\n \n";
            }
            if (!purged[3].isEmpty()) {
                allErrors += "The following Future(s) were old: \n" + purged[3] + "\n \n";
            }
        }
        /**********************************
         * END OF PURGE SECTION
         **********************************/
        return allErrors;
    }

    @Override
    public String toString() {
        return Report.output();
    }
}
